import type { App } from "vue";
import type { Router } from "vue-router";


const map = new WeakMap();

interface RichTextOptions {
  htmlText: string;
  styleText?: string;
  loginCheckMethod?: () => boolean | Promise<boolean>;
  router?: Router;
  phoneCheckRoutes?: string[]; // 需要手机号校验的路由
  phoneCheckMethod?: () => boolean | Promise<boolean>; // 校验手机号的方法
}

function toShadowDom(
  el: HTMLElement,
  htmlText: string,
  styleText = "",
  loginCheckMethod?: () => boolean | Promise<boolean>,
  router?: Router,
  phoneCheckRoutes: string[] = [],
  phoneCheckMethod?: () => boolean | Promise<boolean>
) {
  let shadowRoot;
  if (map.get(el)) {
    shadowRoot = map.get(el);
  } else {
    shadowRoot = el.attachShadow({ mode: "closed" });
    map.set(el, shadowRoot);
  }
  shadowRoot.innerHTML = htmlText;

  const links = shadowRoot.querySelectorAll("a");
  links.forEach((link: HTMLAnchorElement) => {
    link.addEventListener("click", async (e: Event) => {
      e.preventDefault();
      const href = link.getAttribute("href");
      if (!href) return;

      // 登录检查
      let isLoggedIn = true;
      if (loginCheckMethod) {
        isLoggedIn = await loginCheckMethod();
        if (!isLoggedIn) return;
      }

      // 手机号检查
      if (isLoggedIn && phoneCheckRoutes.includes(href) && phoneCheckMethod) {
        const hasPhone = await phoneCheckMethod();
        if (!hasPhone) return;
      }

      // 区分站内路由和外链
      if (router && href.startsWith("/")) {
        router.push(href);
      } else {
        window.location.href = href;
      }
    });
  });

  if (styleText) {
    const style = document.createElement("style");
    style.textContent = styleText;
    shadowRoot.appendChild(style);
  }
}

function handleBindingVal(binding: any) {
  let htmlText, styleText, loginCheckMethod, router, phoneCheckRoutes, phoneCheckMethod;
  if (typeof binding.value === "object") {
    htmlText = binding.value.htmlText;
    styleText = binding.value.styleText;
    loginCheckMethod = binding.value.loginCheckMethod;
    router = binding.value.router;
    phoneCheckRoutes = binding.value.phoneCheckRoutes || [];
    phoneCheckMethod = binding.value.phoneCheckMethod;
  } else {
    htmlText = binding.value;
    phoneCheckRoutes = [];
  }
  return { htmlText, styleText, loginCheckMethod, router, phoneCheckRoutes, phoneCheckMethod };
}

const useRichText = {
  install: (app: App) => {
    app.directive("richText", {
      mounted(el, binding) {
        const { htmlText, styleText, loginCheckMethod, router, phoneCheckRoutes, phoneCheckMethod } =
          handleBindingVal(binding);
        toShadowDom(el, htmlText, styleText, loginCheckMethod, router, phoneCheckRoutes, phoneCheckMethod);
      },
      updated(el, binding) {
        const { htmlText, styleText, loginCheckMethod, router, phoneCheckRoutes, phoneCheckMethod } =
          handleBindingVal(binding);
        toShadowDom(el, htmlText, styleText, loginCheckMethod, router, phoneCheckRoutes, phoneCheckMethod);
      },
    });
  },
};

export default useRichText;
